﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Collections;

namespace FooFun.DataElements.Dtos
{
    public class XmlElementDataElement : DataElement
    {
        public XmlElementDataElement
            (XmlElement node, XmlNode parentNode)
        {
            this.node = node;
            this.parentNode = parentNode;
        }

        public XmlElementDataElement(XmlElement node)
        {
            this.node = node;
            this.parentNode = node.ParentNode;
        }

        XmlNode parentNode;

        public XmlNode ParentNode
        {
            get { return parentNode; }
            set { parentNode = value; }
        }

        private XmlElement node;

        public XmlElement Node
        {
            get { return node; }
            set { node = value; }
        }

        #region IDataElement 成员

        public override object Value
        {
            get
            {
                return node.InnerText;
            }
            set
            {
                if (node.ParentNode == null)
                {
                    parentNode.AppendChild(node);
                }
                node.InnerText = value.ToString();
            }
        }

        public override IDataElement this[string attrName]
        {
            get
            {
                if (attrName.IndexOf("@") == 0)
                {
                    attrName = attrName.Substring(1);
                    XmlAttribute attr = node.Attributes[attrName];
                    if (attr != null)
                    {
                        return new XmlAttributeDataElement(attr);
                    }
                    else
                    {
                        attr = Document.CreateAttribute(attrName);
                        this.node.Attributes.Append(attr);

                        return new XmlAttributeDataElement(attr);
                    }
                }

                XmlNodeList list = node.SelectNodes(attrName);
                if (list != null && list.Count == 1)
                {
                    return new XmlElementDataElement(
                        (XmlElement)list[0]
                        );
                }
                else if (list.Count > 1)
                {
                    return new XmlNodeListDataElement(list);
                }
                else
                {
                    if (this.node.ParentNode == null)
                    {
                        this.parentNode.AppendChild(this.node);
                    }

                    XmlElement ele = Document.CreateElement(attrName);
                    return new XmlElementDataElement(ele, this.node);
                }
            }
            set
            {
                throw new NotImplementedException();
                /*
                if (attrName.IndexOf("@") == 0)
                {
                    attrName = attrName.Substring(1);
                    XmlAttribute attr = node.Attributes[attrName];
                    if (attr != null)
                    {
                        attr.Value = value.Value.ToString();
                    }
                    else
                    {
                        attr
                            = this.Document
                            .CreateAttribute(attrName);

                        attr.Value = value.Value.ToString();

                        this.node.Attributes.Append(attr);
                    }
                }
                else
                {
                    XmlNode ele
                        = this.node.SelectSingleNode(attrName);
                    if (ele == null)
                    {
                        ele = CreateElement(attrName);
                    }

                    ele.InnerXml = value.Value.ToString();
                }
                */
            }
        }

        public override IDataElement Add(IDataElement de)
        {
            XmlElementDataElement nodeEle = (XmlElementDataElement)de;

            this.node.AppendChild(nodeEle.node);

            if (this.node.ParentNode == null)
            {
                this.ParentNode.AppendChild(this.node);
            }

            return nodeEle;
        }

        public override bool IsEmpty
        {
            get
            {
                return !this.node.HasChildNodes;
            }
        }

        public override IDataElement Parent
        {
            get
            {
                XmlElement ele
                    = (XmlElement)this.node.ParentNode;
                return new XmlElementDataElement(ele);
            }
        }


        #endregion

        /*
        private XmlElement CreateElement(string attrName)
        {
            string[] paths = attrName.Split("/".ToCharArray());

            XmlElement parentNode = (XmlElement)this.node;

            foreach (string str in paths)
            {
                XmlElement ele = Document.CreateElement(str);
                parentNode.AppendChild(ele);

                parentNode = ele;
            }

            return parentNode;
        }
        */

        public XmlDocument Document
        {
            get
            {
                return this.node.OwnerDocument;
            }
        }
    }
}
